#include "treasurer.h"
#include "encodedsqldbaccess.h"

#include <assert.h>

#include <QSqlQuery>
#include <QSqlError>
#include <QSqlTableModel>

#include <QFile>
#include <QMessageBox>

namespace
{
    #define DB_COINS            "coins"

    #define DB_COINS_ID         "id"
    #define DB_COINS_SHORT      "short"
    #define DB_COINS_DESC       "desc"
    #define DB_COINS_FINENESS   "fineness"
    #define DB_COINS_WEIGHT     "weight"
    #define DB_COINS_DIAMETER   "diameter"
    #define DB_COINS_QUANTITY   "quantity"
    #define DB_COINS_TYPE       "type"

    #define DB_COINS_PURCHASE_P "purchase_price"
    #define DB_COINS_PURCHASE_D "purchase_date"
    #define DB_COINS_SALE_P     "sale_price"
    #define DB_COINS_SALE_D     "sale_date"


    #define M_COINS_ID          0
    #define M_COINS_SHORT       1
    #define M_COINS_DESC        2
    #define M_COINS_FINENESS    3
    #define M_COINS_WEIGHT      4
    #define M_COINS_DIAMETER    5
    #define M_COINS_QUANTITY    6
    #define M_COINS_TYPE        7

    #define M_COINS_PURCHASE_P  8
    #define M_COINS_PURCHASE_D  9
    #define M_COINS_SALE_P      10
    #define M_COINS_SALE_D      11
}

Treasurer::Treasurer(
    const QString &dbFilePath
,   QObject *parent)
:   QObject(parent)
,   m_db(new EncodedSqlDbAccess(this))
,   m_model(NULL)
{
    m_db->open(dbFilePath);

    if(m_db->isEmpty())
        createTables();
}


Treasurer::~Treasurer()
{
    delete m_db;
    delete m_model;
}


const bool Treasurer::isValid() const
{
    assert(m_db);
    return m_db->isValid();
}


const bool Treasurer::createTables()
{
    assert(m_db->isOpen());

    QSqlDatabase &db = m_db->db();
    QSqlQuery q(db);

    if(!EncodedSqlDbAccess::exec(q, "create table " DB_COINS " ("
        "  " DB_COINS_ID         " INTEGER PRIMARY KEY AUTOINCREMENT"
        ", " DB_COINS_SHORT      " TEXT"
        ", " DB_COINS_DESC       " TEXT"
        ", " DB_COINS_FINENESS   " DECIMAL(12, 8)"
        ", " DB_COINS_WEIGHT     " DECIMAL( 7, 2)"
        ", " DB_COINS_DIAMETER   " DECIMAL( 5, 2)"
        ", " DB_COINS_QUANTITY   " INTEGER"
        ", " DB_COINS_TYPE       " TINYINT"
        ", " DB_COINS_PURCHASE_P " DATE"
        ", " DB_COINS_PURCHASE_D " DECIMAL(18, 2)"
        ", " DB_COINS_SALE_P     " DATE"
        ", " DB_COINS_SALE_D     " DECIMAL(18, 2)"
        ")"))
        return false;

    db.commit();
    return true;
}


QSqlTableModel *Treasurer::model()
{
    if(m_model)
        return m_model;

    setupModel();

    return m_model;
}


void Treasurer::setupModel()
{
    if(m_model)
        delete m_model;

    assert(m_db->isOpen());

    QSqlDatabase &db = m_db->db();

    m_model = new QSqlTableModel(NULL, db);

    m_model->setTable(DB_COINS);
    m_model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    m_model->select();

    m_model->setHeaderData(M_COINS_ID,         Qt::Horizontal, tr("Id"));
    m_model->setHeaderData(M_COINS_SHORT,      Qt::Horizontal, tr("Short Description"));
    m_model->setHeaderData(M_COINS_DESC,       Qt::Horizontal, tr("Description"));
    m_model->setHeaderData(M_COINS_FINENESS,   Qt::Horizontal, tr("Fineness"));
    m_model->setHeaderData(M_COINS_WEIGHT,     Qt::Horizontal, tr("Weight"));
    m_model->setHeaderData(M_COINS_DIAMETER,   Qt::Horizontal, tr("Diameter"));
    m_model->setHeaderData(M_COINS_QUANTITY,   Qt::Horizontal, tr("Quantity"));
    m_model->setHeaderData(M_COINS_TYPE,       Qt::Horizontal, tr("Type"));
    m_model->setHeaderData(M_COINS_PURCHASE_P, Qt::Horizontal, tr("Purchase Price"));
    m_model->setHeaderData(M_COINS_PURCHASE_D, Qt::Horizontal, tr("Purchase Date"));
    m_model->setHeaderData(M_COINS_SALE_P,     Qt::Horizontal, tr("Sale Price"));
    m_model->setHeaderData(M_COINS_SALE_D,     Qt::Horizontal, tr("Sale Date"));
}
